package org.pz.controller;

import ch.qos.logback.core.util.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.RedissonBloomFilter;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * redis 一些使用，没有实际意义，纯练手使用
 * */
@Slf4j
@RestController
@RequestMapping("/redis")
public class RedisController {

    //用来模拟数据
    Map<String, String> map = new HashMap<>();

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //布隆过滤器
    RBloomFilter<String> testBloom;

    private RedissonClient redissonClient;

    public RedisController(RedissonClient redissonClient){

        map.put("age", "100");
        map.put("sex", "1");

        //初始化布隆过滤器
        this.redissonClient = redissonClient;
        testBloom = redissonClient.getBloomFilter("test_bloom");
        /*
         * 调整参数，故意初始化一个容易误判的，
         * param1，初始数组长度
         * param2，误判率
         */
        log.info( "初始化布隆过滤器：{}", testBloom.tryInit(100L, 0.2));
    }

    /**
     * 新增数据
     * */
    @RequestMapping("/save")
    public void save(String key, String value) {
        //模拟数据库数据
        map.put(key, value);
    }

    /**
     * 查询数据
     * */
    @RequestMapping("/find")
    public String find(String key) {
        //能从缓存中拿就直接拿
        if(Boolean.TRUE.equals(redisTemplate.hasKey(key))){
            return redisTemplate.opsForValue().get(key);
        }
        //从缓存中拿不到，就先获取然后存个缓存
        String s = map.get(key);
        redisTemplate.opsForValue().set(key, s);
        return s;
    }

    /**
     * 查询数据，cacheable 版本
     * */
    @RequestMapping("/find/{key}")
    @Cacheable(value = "#root.method.name + '--' + #root.args[0]")
    public String cacheFind(@PathVariable String key) {
        System.out.println("方法执行。。。。");
        return map.get(key);
    }

    /**
     * 布隆过滤器
     * 如果根据同一个哈希函数得到的哈希值不同，那么这两个哈希值的原始输入值肯定不同
     * 如果根据同一个哈希函数得到的两个哈希值相等，两个哈希值的原始输入值有可能相等，有可能不相等
     * */
    @RequestMapping("/bloom")
    public boolean bloom(String key) {
        System.out.println(key);
        return testBloom.add(key);
    }

    /**
     * 接口限流
     * 这里只是模拟一下，实际应该通过 aop 或者拦截器之类的来请求
     * 该接口每分钟限制十个请求
     * */
    String allowRequestKey = "testAllowKey";  //随便起个 key
    int maxRequests = 10;
    int period = 1; //
    TimeUnit timeUnit = TimeUnit.MINUTES;
    @RequestMapping("/allowRequest")
    public boolean allRequest(){
        //每次请求 +1
        Long count = redisTemplate.opsForValue().increment(allowRequestKey, 1);
        if(count == 1){
            redisTemplate.expire(allowRequestKey, period, timeUnit);
        }
        return count <= maxRequests;
    }



}
